﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Lab
{
    class Lab
    {
        static void MainMethod(string[] args)
        {
            Global.Init();

            ApplyStyle();

            Console.ReadLine();
        }

        static void ApplyStyle()
        {
            var Grand = new ParentElement();
            var Parent = new ParentElement();
            var Child = new ChildElement();

            Grand.Resource.Add("ChildStyle",new Style()
                                                {
                                                    Setters=
                                                        {
                                                            new Setter(){ Property="Look",Value="Old"}
                                                        },
                                                    Type=typeof(ChildElement)
                                                });
            Child.StyleKey = "ChildStyle";

            Grand.Content = Parent;
            Parent.Parent = Grand;
            Parent.Content = Child;
            Child.Parent = Parent;
            Child.ApplyStyle();

            Console.WriteLine(Child.Get("Look"));

        }

        static void BaseAccess()
        {
            var u = new Useless();
            u.Set("Look","Old");
            Console.WriteLine(u.Get(7));
        }
    }

    class Base
    {
        public Dictionary<int,object> Dict = new Dictionary<int, object>();

        public int GetPropertyId(Type ty,string name)
        {
            // should check whether props are inited for this type

            return Global.Props[ty][name];
        }

        public virtual int GetPropertyId(string name)
        {
            return GetPropertyId(typeof(Base),name);
        }

        public void Set(string name,object value)
        {
            int id = GetPropertyId(name);
            Dict[id] = value;
        }

        public object Get(string name)
        {
            int id = GetPropertyId(name);
            return Dict[id];
        }

        public void Set(int id,object value)
        {
            Dict[id] = value;
        }

        public object Get(int id)
        {
            return Dict[id];
        }
    }

    class Useful : Base
    {
        public override int GetPropertyId(string name)
        {
            return Global.Props[typeof(Useful)][name];
        }
    }

    class Useless : Useful
    {
        public override int GetPropertyId(string name)
        {
            return Global.Props[typeof(Useless)][name];
        }
    }

    class Global
    {
        /// <summary>
        /// Find PropertyId by name
        /// </summary>
        public static Dictionary<Type,Dictionary<string,int>> Props = new Dictionary<Type,Dictionary<string, int>>();

        public static int GetPropertyId(Type ty,string name)
        {
            return Props[ty][name];
        }

        public static void SetPropertyId(Type ty,string name,int id)
        {
            if(Props.ContainsKey(ty))
                Props[ty][name] = id;
            else
            {
                Props[ty] = new Dictionary<string, int>();
                Props[ty][name] = id;
            }
        }

        public static void CopyPropertyId(Type self,Type parent)
        {
            if(!Props.ContainsKey(self))
                Props[self] = new Dictionary<string, int>();

            if (Props.ContainsKey(parent)&&Props[parent].Count>0)
                foreach (var prop in Props[parent])
                {
                    Props[self].Add(prop.Key,prop.Value);
                }
        }

        /// <summary>
        /// Find PropertyInfo by Id
        /// </summary>
        public static Dictionary<int,PropertyInfo> PropsDef = new Dictionary<int, PropertyInfo>();

        public static void Init()
        {
            Props[typeof(Useful)] = new Dictionary<string,int>{{"Age",5},{"Text",6}};
            Props[typeof(Useless)] = new Dictionary<string,int>{{"Age",5},{"Text",6},{"Look",7}};

            Props[typeof(ParentElement)] = new Dictionary<string,int>{{"Age",5},{"Text",6}};
            Props[typeof(ChildElement)] = new Dictionary<string,int>{{"Age",5},{"Text",6},{"Look",7}};

            PropsDef = new Dictionary<int, PropertyInfo>()
                           {
                               {5,new PropertyInfo("Age",typeof(int),0)},
                               {6,new PropertyInfo("Text",typeof(string),"")},
                               {7,new PropertyInfo("Look",typeof(string),"")}
                           };
        }

        public static void InitType(Type ty)
        {
            
        }
    }

    class Template
    {
        
    }

    class ElementTemplate
    {
        
    }

    class DataTemplate
    {
        
    }

    class Style
    {
        public Type Type;
        public List<Setter> Setters = new List<Setter>();
    }

    class Setter
    {
        public string Property;
        public object Value;
    }

    class ClassInfo
    {
        
    }

    class PropertyInfo
    {
        public string Name;
        public object Default;
        public Type PropType;
        public bool Attach;

        public PropertyInfo()
        {
            
        }

        public PropertyInfo(string name,Type type,object value)
        {
            Name = name;
            Default = value;
            PropType = type;
        }
    }

    class Collection : Base
    {
        
    }

    class Element : Base
    {
        public Element Parent;
        public Dictionary<string,object> Resource = new Dictionary<string, object>();

        public string StyleKey = "";
        public Style Style = null;

        public void ApplyStyle()
        {
            if (StyleKey != "" && Style == null)
                Style = (Style) FindResource(StyleKey);
            
            Console.WriteLine(Style.Type);
            if(Style!=null && Style.Type==GetType())
            {
                
                foreach (var i in Style.Setters)
                {
                    Set(i.Property,i.Value);
                }
            }

        }

        public object FindResource(string key)
        {
            if (Resource.ContainsKey(key))
                return Resource[key];
            else if (Parent != null)
                return Parent.FindResource(key);
            else
                return null;
        }
    }

    class ParentElement : Element
    {
        public Element Content;


        public override int GetPropertyId(string name)
        {
            return Global.Props[typeof(ParentElement)][name];
        }
    }

    class ChildElement : Element
    {
        public override int GetPropertyId(string name)
        {
            return Global.Props[typeof(ChildElement)][name];
        }
        
    }

    class SimpleElement : Base
    {
        
    }

    class Bind
    {
        
    }

    class Binding
    {
        
    }
}
